var sw = 20,//小格子的宽
    sh = 20,//小格子的高
    tr = 30,//行数
    td = 30;//列数

var snake = null,//蛇的实例
    food = null,//食物的实例
    game = null;//游戏的实例

// 创建方块的构造函数
function Square(x, y, classname) {
    /* 坐标
    0 0         0,0
    20,0        1,0
    30,0        2,0 */
    // 将传进来的值乘以宽高
    this.x = x * sw;
    this.y = y * sh;
    this.class = classname;

    // 创建一个div,方块对应的dom元素
    this.viewContent = document.createElement('div');
    // 将传进来的值给div
    this.viewContent.className = this.class;
    // 将创建的div添加到snakeWrap的子元素,方块的父级
    this.parent = document.getElementById('snakeWrap');
}

//将属性挂到原型上
Square.prototype.create = function () {//创建方块dom
    this.viewContent.style.position = 'absolute';
    this.viewContent.style.width = sw + 'px';
    this.viewContent.style.height = sh + 'px';
    this.viewContent.style.left = this.x + 'px';
    this.viewContent.style.top = this.y + 'px';

    // 将创建的方块dom追加到页面上
    this.parent.appendChild(this.viewContent);
}
// 移除方块
Square.prototype.remove = function () {
    this.parent.removeChild(this.viewContent);
}


// 蛇
function Snake() {
    this.head = null;//存蛇头的信息
    this.tail = null;//存蛇尾的信息
    this.pos = [];//存储蛇身上每一个方块的位置

    this.directionNum = {//存储蛇走的方向,用一个对象表示
        left: {
            x: -1,
            y: 0,
            rotate: 180
        },
        right: {
            x: 1,
            y: 0,
            rotate: 0
        },
        up: {
            x: 0,
            y: -1,
            rotate: -90
        },
        down: {
            x: 0,
            y: 1,
            rotate: 90
        }
    }
}
Snake.prototype.init = function () {
    // 创建蛇头
    var snakeHead = new Square(2, 0, 'snakeHead');
    snakeHead.create();
    this.head = snakeHead;//存入蛇头的信息
    this.pos.push([2, 0]);//将蛇头的位置存起来

    var snakeBody1 = new Square(1, 0, 'snakeBody');
    snakeBody1.create();
    this.pos.push([1, 0]);//将蛇身体的位置存起来

    var snakeBody2 = new Square(0, 0, 'snakeBody');
    snakeBody2.create();
    this.tail = snakeBody2;//将蛇尾的信息存起来
    this.pos.push([0, 0]);//将蛇身体的位置存起来


    // 形成链表关系
    snakeHead.last = null;
    snakeHead.next = snakeBody1;

    snakeBody1.last = snakeHead;
    snakeBody1.next = snakeBody2;

    snakeBody2.last = snakeBody1;
    snakeBody2.next = null;

    // 给蛇添加一条属性,表示蛇走的方向
    this.direction = this.directionNum.right;//默认让蛇往右走
}

//这个方法用来获取蛇头的下一个位置对应的元素,要根据元素做不同的事情
Snake.prototype.getNextPos = function () {
    var nextPos = [//蛇头要走下一个的坐标
        this.head.x / sw + this.direction.x,
        this.head.y / sh + this.direction.y
    ]

    //下个点是自己,代表撞到了自己,游戏结束
    var selfCollied = false;//是否撞到了自己
    this.pos.forEach(function (value) {
        if (value[0] == nextPos[0] && value[1] ==nextPos[1]) {
            //如果数组中的两个值都相等,说明撞到了自己的身体
            selfCollied = true;
        }

    });
    if (selfCollied) {
        console.log('撞到自己了');
        this.strategies.die.call(this);//改变this指向,让他指向snake
        return;
    }

    //下个点是围墙,游戏结束
    if (nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
        console.log('撞到围墙了');
        this.strategies.die.call(this);//改变this指向,让他指向snake
        return;
    }

    //下个点是食物,吃
    if(food && food.pos[0]==nextPos[0]&&food.pos[1]==nextPos[1]){
        //如果这个条件成立,说明蛇头下一个就吃到食物了
        console.log(111);
        this.strategies.eat.call(this);
        return;
    }


    //下个点什么都不是 走
    this.strategies.move.call(this);//改变this指向,让他指向snake
};


//处理碰撞之后的事情
Snake.prototype.strategies = {
    move: function (format) {//设个参数决定要不要删除最后一个蛇尾
        //创建新身体,在旧蛇头的位置
        var newBody = new Square(this.head.x / sw, this.head.y / sh, 'snakeBody');
        //更新链表的关系
        newBody.next = this.head.next;
        newBody.next.last=newBody;
        newBody.last = null;


        this.head.remove();//把原来的蛇头删除
        newBody.create();//添加一个新的蛇身体在旧蛇头的位置


        //创建一个新蛇头(旧蛇头要走的位置)
        var newHead = new Square(this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y, 'snakeHead');
        //更新链表关系
        newHead.next = newBody;
        newHead.last = null;
        newBody.last = newHead;
        newHead.viewContent.style.transform='rotate('+this.direction.rotate+'deg)';
        newHead.create();

        //蛇身上的每一块方块也要更新
        this.pos.splice(0, 0, [this.head.x / sw + this.direction.x, this.head.y / sh + this.direction.y]);//将添加的蛇头移到数组的第一个位置
        this.head = newHead;//更新蛇头的信息

        if (!format) {//如果format为false,则要删除(除了吃之外)
            this.tail.remove();
            this.tail = this.tail.last;
            this.pos.pop();
        }

    },
    eat: function () {
        this.strategies.move.call(this,true);
        food.remove();//先移除被吃的苹果
        createFood();
        //食物被吃掉了,再随机生成一个
        game.score++;//吃掉一个,让分数加一
    },
    die: function () {
        game.over();//游戏结束
    }
}

snake = new Snake();

function createFood() {
    //食物小方块的坐标
    var x = null;
    var y = null;
    var include = true;//跳出循环的条件,true表示食物的坐标在蛇身上(要继续循环),false表示食物不在蛇的身上(不循环)

    while (include) {
        //随机生成食物的坐标
        x = Math.round(Math.random() * (td - 1));
        y = Math.round(Math.random() * (tr - 1));

        snake.pos.forEach(function (value) {

            if (x!=value[0] && y!=value[1]) {
                //这个条件说明生成的食物没有在蛇的身上找到,
                include = false;
            }
        });
    }
    //生成食物
    food = new Square(x, y, 'food');
    food.pos=[x,y];//存储食物的坐标,用于跟蛇头要走的下一个点做对比
    food.create();
}



//创建游戏逻辑
function Game() {
    this.timer = null;
    this.score = 0;
}

Game.prototype.init = function () {
    snake.init();
    // snake.getNextPos();
    createFood();

    //键盘事件
    document.onkeydown = function (ev) {
        if (ev.keyCode == 37 && snake.direction != snake.directionNum.right) {
            snake.direction = snake.directionNum.left;
        } else if (ev.keyCode == 38 && snake.direction != snake.directionNum.down) {
            snake.direction = snake.directionNum.up;
        } else if (ev.keyCode == 39 && snake.direction != snake.directionNum.left) {
            snake.direction = snake.directionNum.right;
        } else if (ev.keyCode == 40 && snake.direction != snake.directionNum.up) {
            snake.direction = snake.directionNum.down;
        }
    }
    this.start();

}
Game.prototype.start = function () {//开始游戏
    this.timer = setInterval(function () {
        snake.getNextPos();
    }, 200);
}
Game.prototype.pause=function(){
    clearInterval(this.timer);
}
Game.prototype.over=function(){
    clearInterval(this.timer);//清除定时器
    alert('你的得分为:'+this.score);

    //游戏回到初始的状态
    var snakeWrap=document.getElementById('snakeWrap');
    snakeWrap.innerHTML='';

    snake=new Snake();
    game=new Game;

    var startBtnWrap=document.querySelector('.startBtn');
    startBtnWrap.style.display='block';
}

game = new Game();

//开启游戏
var startBtn=document.querySelector('.startBtn button');
startBtn.onclick=function(){
    startBtn.parentNode.style.display='none';
    game.init();
}

//暂停游戏
var snakeWrap=document.getElementById('snakeWrap');
var pauseBtn=document.querySelector('.pauseBtn button');
//点击屏幕时暂停游戏
snakeWrap.onclick=function(){
    game.pause();
    pauseBtn.parentNode.style.display='block';
}

//点击开启按钮就进行游戏
pauseBtn.onclick=function(){
    game.start();
    pauseBtn.parentNode.style.display='none';
}